/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.railway.app;

import com.railway.utils.CustomTableModel;
import com.railway.classes.Route;
import com.railway.utils.CustomScrollBarUI;
import com.railway.utils.Double2DecimalRenderer;
import com.railway.utils.FareTableModel;
import com.railway.utils.RestServer;
import com.railway.utils.SpinnerCellEditor;
import com.railway.utils.Toast;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 *
 * @author Kenny
 */
public class FarePanel extends javax.swing.JPanel {

    Image imgArrow = new ImageIcon(this.getClass().getResource("/com/railway/image/arrow.png")).getImage();
    private ArrayList<String> colName;
    private ArrayList<ArrayList<Object>> rowData;
    private CustomTableModel ctmFare;
    private FareTableModel ftmStations;
    private DefaultListModel<Route> dlmRoute;
    private JSONObject json;
    private JSONArray jsonArray;
    private int rid;
    private int noOfStations;

    /**
     * Creates new form FarePanel
     */
    public FarePanel() {
        initComponents();
        populateRouteListData();
    }

    private void populateRouteListData() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String result = RestServer.httpGet("route", "");
                try {
                    json = new JSONObject(result);
                    boolean error = json.optBoolean("error");
                    if (!error) {
                        int statuscode = json.getInt("status");
                        if (statuscode == 200) {
                            dlmRoute = new DefaultListModel<>();
                            jsonArray = json.getJSONArray("content");
                            for (int i = 0; i < jsonArray.length(); i++) {
                                Route temp = new Route();
                                temp.setRid(jsonArray.getJSONObject(i).getInt("rid"));
                                temp.setRouteName(jsonArray.getJSONObject(i).getString("routeName"));
                                temp.setStatus(jsonArray.getJSONObject(i).getString("status"));
                                dlmRoute.addElement(temp);
                            }
                            jltAvailableRoute.setModel(dlmRoute);
                        } else {
                            Toast.makeText(FarePanel.this, "No routes found.", Toast.LENGTH_SHORT).display();
                        }
                    } else {
                        Toast.makeText(FarePanel.this, json.getString("message"), Toast.LENGTH_SHORT).display();
                    }
                } catch (JSONException ex) {
                }
            }
        }).start();
    }

    private void populateFareTableData(final int rid) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String result = RestServer.httpGet("station/fare", "" + rid);
                try {
                    json = new JSONObject(result);
                    boolean error = json.optBoolean("error");
                    if (!error) {
                        int statuscode = json.getInt("status");
                        if (statuscode == 200) {
                            colName = new ArrayList<>();
                            rowData = new ArrayList<>();
                            colName.add("Station Name");
                            colName.add("Fare");
                            jsonArray = json.getJSONArray("content");
                            for (int i = 0; i < jsonArray.length(); i++) {
                                ArrayList<Object> temp = new ArrayList<>();
                                temp.add(jsonArray.getJSONObject(i).getString("stationName"));
                                temp.add(jsonArray.getJSONObject(i).getDouble("fare"));
                                rowData.add(temp);
                            }
                            ctmFare = new CustomTableModel(colName, rowData);
                            jtbStationFare.setModel(ctmFare);
                            jtbStationFare.getColumnModel().getColumn(1).setCellRenderer(new Double2DecimalRenderer());
                        } else {
                            Toast.makeText(FarePanel.this, "No stations found for this route", Toast.LENGTH_SHORT).display();
                        }
                    } else {
                        Toast.makeText(FarePanel.this, json.getString("message"), Toast.LENGTH_SHORT).display();
                    }
                } catch (JSONException ex) {
                }
            }
        }).start();
    }

    private void populateStationTableData(final int rid) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String result = RestServer.httpGet("station/fare", "" + rid);
                try {
                    json = new JSONObject(result);
                    rowData = new ArrayList<>();
                    boolean error = json.optBoolean("error");
                    if (!error) {
                        int statuscode = json.getInt("status");
                        if (statuscode == 200) {
                            String[] colNames = {"sid", "Station Name", "Fare Start From First Station"};
                            jsonArray = json.getJSONArray("content");
                            for (int i = 0; i < jsonArray.length(); i++) {
                                ArrayList<Object> temp = new ArrayList<>();
                                temp.add(jsonArray.getJSONObject(i).getString("sid"));
                                temp.add(jsonArray.getJSONObject(i).getString("stationName"));
                                temp.add(jsonArray.getJSONObject(i).getDouble("fare"));
                                rowData.add(temp);
                            }
                            Object[][] rowDatas = new Object[rowData.size()][];
                            for (int i = 0; i < rowData.size(); i++) {
                                ArrayList<Object> arrayList = rowData.get(i);
                                rowDatas[i] = arrayList.toArray(new Object[arrayList.size()]);
                            }
                            DefaultTableModel dtmStation = new DefaultTableModel(rowDatas, colNames) {
                                @Override
                                public boolean isCellEditable(int row, int col) {
                                    if (col == 2) {
                                        return true;
                                    } else {
                                        return false;
                                    }
                                }
                            };
                            jTable1.setModel(dtmStation);
                            jTable1.removeColumn(jTable1.getColumnModel().getColumn(0));
                            TableColumn tc = jTable1.getColumnModel().getColumn(1);
                            tc.setCellEditor(new SpinnerCellEditor());
                        } else {
                            Toast.makeText(FarePanel.this, "No stations found for this route", Toast.LENGTH_SHORT).display();
                        }
                    } else {
                        Toast.makeText(FarePanel.this, json.getString("message"), Toast.LENGTH_SHORT).display();
                    }
                } catch (JSONException ex) {
                }
            }
        }).start();
    }

    private String buildQuery(ArrayList stations, ArrayList fare) {
        StringBuilder sb = new StringBuilder("(CASE sid ");
        StringBuilder sb2 = new StringBuilder();
        for (int i = 0; i < stations.size(); i++) {
            sb.append("WHEN ").append(stations.get(i).toString()).append(" THEN ").append(fare.get(i)).append(" ");
            sb2.append(stations.get(i).toString()).append((i == (stations.size() - 1) ? "" : ", "));
        }
        sb.append("END)").append(" WHERE sid IN (").append(sb2.toString()).append(")").append(" AND rid = :rid;");
        return sb.toString();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jpFareArrow = new javax.swing.JPanel(){
            protected void paintComponent(Graphics g){
                super.paintComponent(g);
                g.drawImage(imgArrow, 0, 0, getWidth(), imgArrow.getHeight(this), this);
            }
        };
        jpFarePanel = new javax.swing.JPanel();
        jlblAvailableRoute = new javax.swing.JLabel();
        jsprRoute = new javax.swing.JSeparator();
        jspAvailableRoute = new javax.swing.JScrollPane();
        jltAvailableRoute = new javax.swing.JList();
        jlblStationFare = new javax.swing.JLabel();
        jsprStationFare = new javax.swing.JSeparator();
        jspStationFare = new javax.swing.JScrollPane();
        jtbStationFare = new javax.swing.JTable();
        jPanel1 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        jtfRoute = new javax.swing.JTextField();
        jbtSubmit = new javax.swing.JButton();
        jbtReset = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();

        setBackground(new java.awt.Color(255, 255, 255));
        setPreferredSize(new java.awt.Dimension(860, 375));
        setLayout(null);

        jpFareArrow.setBackground(new java.awt.Color(255, 255, 255));

        javax.swing.GroupLayout jpFareArrowLayout = new javax.swing.GroupLayout(jpFareArrow);
        jpFareArrow.setLayout(jpFareArrowLayout);
        jpFareArrowLayout.setHorizontalGroup(
            jpFareArrowLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 180, Short.MAX_VALUE)
        );
        jpFareArrowLayout.setVerticalGroup(
            jpFareArrowLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 10, Short.MAX_VALUE)
        );

        add(jpFareArrow);
        jpFareArrow.setBounds(225, 0, 180, 10);

        jpFarePanel.setBackground(new java.awt.Color(255, 255, 255));
        jpFarePanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(220, 220, 220), 2));
        jpFarePanel.setLayout(null);

        jlblAvailableRoute.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        jlblAvailableRoute.setText("AVAILABLE ROUTES");
        jpFarePanel.add(jlblAvailableRoute);
        jlblAvailableRoute.setBounds(555, 0, 290, 20);
        jpFarePanel.add(jsprRoute);
        jsprRoute.setBounds(555, 20, 290, 5);

        jspAvailableRoute.getVerticalScrollBar().setUI(new CustomScrollBarUI());

        jltAvailableRoute.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
        jltAvailableRoute.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jltAvailableRoute.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                jltAvailableRouteValueChanged(evt);
            }
        });
        jspAvailableRoute.setViewportView(jltAvailableRoute);

        jpFarePanel.add(jspAvailableRoute);
        jspAvailableRoute.setBounds(555, 25, 290, 130);

        jlblStationFare.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        jlblStationFare.setText("STATIONS AND FARES");
        jpFarePanel.add(jlblStationFare);
        jlblStationFare.setBounds(555, 155, 290, 20);
        jpFarePanel.add(jsprStationFare);
        jsprStationFare.setBounds(555, 175, 290, 5);

        jspStationFare.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        jspStationFare.getVerticalScrollBar().setUI(new CustomScrollBarUI());

        jtbStationFare.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {

            }
        ));
        jspStationFare.setViewportView(jtbStationFare);

        jpFarePanel.add(jspStationFare);
        jspStationFare.setBounds(555, 180, 290, 175);

        jPanel1.setBackground(new java.awt.Color(255, 255, 255));
        jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(220, 220, 220), 2));
        jPanel1.setLayout(null);

        jButton1.setBackground(new java.awt.Color(155, 89, 182));
        jButton1.setFont(new java.awt.Font("Segoe UI Emoji", 0, 14)); // NOI18N
        jButton1.setForeground(new java.awt.Color(255, 255, 255));
        jButton1.setText("Update Route Fare");
        jButton1.setFocusPainted(false);
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });
        jPanel1.add(jButton1);
        jButton1.setBounds(5, 5, 530, 50);

        jLabel1.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
        jLabel1.setText("Route");
        jPanel1.add(jLabel1);
        jLabel1.setBounds(90, 70, 140, 30);

        jtfRoute.setEditable(false);
        jtfRoute.setBackground(new java.awt.Color(250, 250, 250));
        jtfRoute.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
        jtfRoute.setEnabled(false);
        jPanel1.add(jtfRoute);
        jtfRoute.setBounds(250, 70, 200, 30);

        jbtSubmit.setBackground(new java.awt.Color(39, 174, 96));
        jbtSubmit.setFont(new java.awt.Font("Segoe UI Emoji", 0, 14)); // NOI18N
        jbtSubmit.setForeground(new java.awt.Color(255, 255, 255));
        jbtSubmit.setText("Submit");
        jbtSubmit.setEnabled(false);
        jbtSubmit.setFocusPainted(false);
        jbtSubmit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbtSubmitActionPerformed(evt);
            }
        });
        jPanel1.add(jbtSubmit);
        jbtSubmit.setBounds(360, 280, 170, 50);

        jbtReset.setBackground(new java.awt.Color(39, 174, 96));
        jbtReset.setFont(new java.awt.Font("Segoe UI Emoji", 0, 14)); // NOI18N
        jbtReset.setForeground(new java.awt.Color(255, 255, 255));
        jbtReset.setText("Reset");
        jbtReset.setFocusPainted(false);
        jbtReset.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbtResetActionPerformed(evt);
            }
        });
        jPanel1.add(jbtReset);
        jbtReset.setBounds(10, 280, 170, 50);

        jScrollPane1.setViewportView(jTable1);

        jScrollPane1.getVerticalScrollBar().setUI(new CustomScrollBarUI());

        jPanel1.add(jScrollPane1);
        jScrollPane1.setBounds(90, 105, 360, 160);

        jpFarePanel.add(jPanel1);
        jPanel1.setBounds(5, 5, 540, 350);

        add(jpFarePanel);
        jpFarePanel.setBounds(5, 10, 850, 360);
    }// </editor-fold>//GEN-END:initComponents

    private void jltAvailableRouteValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_jltAvailableRouteValueChanged
        if (!evt.getValueIsAdjusting()) {
            int routeid = ((Route) jltAvailableRoute.getSelectedValue()).getRid();
            populateFareTableData(routeid);
        }
    }//GEN-LAST:event_jltAvailableRouteValueChanged

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        if (!jltAvailableRoute.getSelectedValuesList().isEmpty()) {
            jtfRoute.setEnabled(true);
            jbtSubmit.setEnabled(true);
            jtfRoute.setText(((Route) jltAvailableRoute.getSelectedValue()).getRouteName());
            rid = ((Route) jltAvailableRoute.getSelectedValue()).getRid();
            populateStationTableData(rid);
        } else {
            Toast.makeText(this, "Please select from the route list first.", Toast.LENGTH_SHORT).display();
        }
    }//GEN-LAST:event_jButton1ActionPerformed

    private void jbtResetActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jbtResetActionPerformed
        jtfRoute.setText(null);
        jTable1.setModel(new DefaultTableModel(0, 0));
        jtfRoute.setEnabled(false);
        rid = 0;
        noOfStations = 0;
        jbtSubmit.setEnabled(false);
    }//GEN-LAST:event_jbtResetActionPerformed

    private void jbtSubmitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jbtSubmitActionPerformed
        if (jTable1.isEditing()) {
            jTable1.getCellEditor().stopCellEditing();
        }
        ArrayList<String> stations = new ArrayList<>();
        ArrayList<Double> fare = new ArrayList<>();
        boolean notCorrect = false;
        int rowCount = jTable1.getRowCount();
        for (int i = 0; i < rowCount; i++) {
            stations.add(jTable1.getModel().getValueAt(i, 0).toString());
            if (i != (rowCount - 1)) {
                if ((Double) jTable1.getValueAt(i, 1) > (Double) jTable1.getValueAt(i + 1, 1)) {
                    notCorrect = true;
                    break;
                } else {
                    fare.add((Double) jTable1.getValueAt(i, 1));
                }
            } else {
                fare.add((Double) jTable1.getValueAt(i, 1));
            }
        }
        if (notCorrect) {
            Toast.makeText(this, "You cannot set one station's fare greater than the next station.", Toast.LENGTH_LONG).display();
        } else {
            Map<String, Object> data = new HashMap<>();
            data.put("query", buildQuery(stations, fare));
            String result = RestServer.httpPut("stationfare", data, "" + rid);
            try {
                json = new JSONObject(result);
                boolean error = json.optBoolean("error");
                if (!error) {
                    int statuscode = json.getInt("status");
                    if (statuscode == 200) {
                        Toast.makeText(this, "Fares successfully updated.", Toast.LENGTH_SHORT).display();
                        populateFareTableData(rid);
                    } else {
                        Toast.makeText(this, "Unable to update fares now, please try again later.", Toast.LENGTH_SHORT).display();
                    }
                } else {
                    Toast.makeText(this, json.getString("message"), Toast.LENGTH_SHORT).display();
                }
            } catch (JSONException ex) {
            }
        }
    }//GEN-LAST:event_jbtSubmitActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable1;
    private javax.swing.JButton jbtReset;
    private javax.swing.JButton jbtSubmit;
    private javax.swing.JLabel jlblAvailableRoute;
    private javax.swing.JLabel jlblStationFare;
    private javax.swing.JList jltAvailableRoute;
    private javax.swing.JPanel jpFareArrow;
    private javax.swing.JPanel jpFarePanel;
    private javax.swing.JScrollPane jspAvailableRoute;
    private javax.swing.JScrollPane jspStationFare;
    private javax.swing.JSeparator jsprRoute;
    private javax.swing.JSeparator jsprStationFare;
    private javax.swing.JTable jtbStationFare;
    private javax.swing.JTextField jtfRoute;
    // End of variables declaration//GEN-END:variables
}
